package com.example.demo.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.*;
import com.example.demo.enums.PwdEnum;
import com.example.demo.enums.RoleEnum;
import com.example.demo.mapper.*;
import com.example.demo.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

    @Resource
    UserMapper userMapper;
    @Resource
    RoleMapper roleMapper;
    @Resource
    PermissionMapper permissionMapper;
    @Resource
    UserRoleMapper userRoleMapper;
    @Resource
    PeopleMapper peopleMapper;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder; //注入bcryct加密

    @PostMapping("/login")
    public Result<?> login(@RequestBody SysUser sysUserParam) throws Exception {
        SysUser sysUserPwd = userMapper.selectByName(sysUserParam.getUsername());
        if (sysUserPwd == null){
            return Result.error("-1", "此用户不存在");
        }
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", sysUserParam.getUsername());
        queryWrapper.eq("password", sysUserPwd.getPassword());
        SysUser res = userMapper.selectOne(queryWrapper);

//        String password = AesEncryptUtils.decrypt(userParam.getPassword(), "f8db034bda44rtkb");
        // 判断密码是否正确
        if (!bCryptPasswordEncoder.matches(sysUserParam.getPassword(), sysUserPwd.getPassword())) {
            return Result.error("-1", "密码错误");
        }
        if (res == null) {
            return Result.error("-1", "用户名或密码错误");
        }
        HashSet<SysPermission> sysPermissionSet = new HashSet<>();
        // 1. 从user_role表通过用户id查询所有的角色信息
        Integer userId = res.getId();
        List<SysUserRole> sysUserRoles = roleMapper.getUserRoleByUserId(userId);
        ArrayList<String> roleList = new ArrayList<>();
        for(SysUserRole item : sysUserRoles){
            SysRole sysRole = roleMapper.selectById(item.getRoleId());
            roleList.add(sysRole.getName());
        }
        res.setRoles(roleList);
//        List<UserRole> userRoles = roleMapper.getUserRoleByUserId(userId);
//        // 设置角色id
//        res.setRoles(userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList()));
        for (SysUserRole sysUserRole : sysUserRoles) {
            // 2.根据roleId从role_permission表查询出所有的permissionId
            List<SysRolePermission> sysRolePermissions = permissionMapper.getRolePermissionByRoleId(sysUserRole.getRoleId());
            for (SysRolePermission sysRolePermission : sysRolePermissions) {
                Integer permissionId = sysRolePermission.getPermissionId();
                // 3. 根据permissionId查询permission信息
                SysPermission sysPermission = permissionMapper.selectById(permissionId);
                sysPermissionSet.add(sysPermission);
            }
        }
        // 对资源根据id进行排序
        LinkedHashSet<SysPermission> sortedSet = sysPermissionSet.stream().sorted(Comparator.comparing(SysPermission::getId)).collect(Collectors.toCollection(LinkedHashSet::new));
        //设置当前用户的资源信息
        res.setSysPermissions(sortedSet);

        // 生成token
        String token = TokenUtils.genToken(res);
        res.setToken(token);
        return Result.success(res);
    }

    @PostMapping("/register")
    public Result<?> register(@RequestBody @Validated SysUser sysUser) {
//        User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, user.getUsername()));
        SysUser res = userMapper.selectByName(sysUser.getUsername());
        if (res != null) {
            return Result.error("-1", "用户名重复");
        }
//        if (user.getPassword() == null) {
//            user.setPassword("123456");
//        }
        SysUser sysUserInfo = SysUser.builder()
                .username(sysUser.getUsername())
                .password(bCryptPasswordEncoder.encode(sysUser.getPassword()))
                .build();

        userMapper.insert(sysUserInfo);

        SysUserRole sysUserRole = SysUserRole.builder()
                .userId(sysUserInfo.getId())
                .roleId(RoleEnum.USER.getRoleId())
                .build();
        userRoleMapper.insert(sysUserRole);
        return Result.success();
    }

    @PostMapping
    public Result<?> save(@RequestBody SysUser sysUser) {
        if (sysUser.getPassword() == null) {
            sysUser.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
        }
        LambdaQueryWrapper<SysPeople> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SysPeople::getPhone, sysUser.getUsername());
        SysPeople sysPeople = peopleMapper.selectOne(wrapper);
        if(sysPeople != null){
            sysUser.setPeopleId(sysPeople.getId());
            userMapper.insert(sysUser);

            sysPeople.setUserId(sysUser.getId());
            peopleMapper.updateById(sysPeople);
        }else{
            userMapper.insert(sysUser);
        }

        List<String> roles = sysUser.getRoleComments();
        for(String item : roles){
            SysRole sysRole = roleMapper.getRoleByName(item);
            SysUserRole sysUserRole = SysUserRole.builder()
                    .userId(sysUser.getId())
                    //.roleId(RoleEnum.USER.getRoleId())
                    .roleId(sysRole.getId())
                    .build();
            userRoleMapper.insert(sysUserRole);
        }

        return Result.success();
    }

    @PutMapping
    public Result<?> update(@RequestBody SysUser sysUser) {
        userRoleMapper.deleteByUserRoleId(Long.valueOf(sysUser.getId()));
        List<String> roles = sysUser.getRoleComments();
        for(String item : roles){
            SysRole sysRole = roleMapper.getRoleByName(item);
            SysUserRole sysUserRole = SysUserRole.builder()
                    .userId(sysUser.getId())
                    //.roleId(RoleEnum.USER.getRoleId())
                    .roleId(sysRole.getId())
                    .build();
            userRoleMapper.insert(sysUserRole);
        }

        userMapper.updateById(sysUser);
        return Result.success();
    }

//    @PutMapping("/pass")
//    public Result<?> pass(@RequestBody Map<String, Object> map) {
//        User user = userMapper.selectById((Integer) map.get("userId"));
//        if (user== null) {
//            return Result.error("-1", "未找到用户");
//        }
//        if (!bCryptPasswordEncoder.matches(map.get("password").toString(), user.getPassword())) {
//            return Result.error("-1", "密码错误");
//        }
//        map.put("newPass", (bCryptPasswordEncoder.encode(map.get("newPass").toString())));
//        userMapper.updatePass(map);
//        return Result.success();
//    }

    @PutMapping("/pass")
    public Result<?> pass(@RequestParam Long id, @RequestParam String oldPass, @RequestParam String newPass) {
        SysUser sysUser = userMapper.selectById(id);
        if (sysUser == null) {
            return Result.error("-1", "未找到用户");
        }
        if (!bCryptPasswordEncoder.matches(oldPass.toString(), sysUser.getPassword())) {
            return Result.error("-1", "密码错误");
        }
        if (oldPass.equals(newPass)) {
            return Result.error("-1", "新旧密码不能一致");
        }
        sysUser.setPassword(bCryptPasswordEncoder.encode(newPass.toString()));
        userMapper.updateById(sysUser);
        return Result.success();
    }

    // 改变权限接口
    @PutMapping("/changeRole")
    public Result<?> changeRole(@RequestBody SysUser sysUser) {
        if(roleMapper.getUserRoleByUserId(sysUser.getId()) != null){
            roleMapper.deleteRoleByUserId(sysUser.getId());
        }
        // 先根据角色id删除所有的角色跟权限的绑定关系

        for(String comment : sysUser.getRoleComments()){
            SysRole sysRole = roleMapper.getRoleByName(comment);
            roleMapper.insertUserRole(sysUser.getId(), sysRole.getId());
        }

        // 再新增 新的绑定关系
//        for (Integer roleId : user.getRoles()) {
//            roleMapper.insertUserRole(user.getId(), roleId);
//        }

// 获取当前登录用户的角色id列表
//        User currentUser = getUser();
// 如果当前登录用户的角色列表包含需要修改的角色id，那么就重新登录
//        if (user.getId().equals(currentUser.getId())) {
//            return Result.success(true);
//        }
//如果不包含，则返回false，不需要重新登录。
        return Result.success();
    }

    @DeleteMapping("/{id}")
    public Result<?> update(@PathVariable Long id) {
        userRoleMapper.deleteByUserRoleId(id);
        userMapper.deleteById(id);
        return Result.success();
    }

//    @GetMapping("/{id}")
//    public Result<?> getById(@PathVariable Long id) {
//        return Result.success(userMapper.selectById(id));
//    }

    @GetMapping("/{id}")
    public Result<?> getById(@PathVariable Long id) {
        HashSet<SysPermission> sysPermissionSet = new HashSet<>();
        SysUser res = userMapper.selectById(id);
        // 1. 从user_role表通过用户id查询所有的角色信息
//        Integer userId = res.getId();
//        List<UserRole> userRoles = roleMapper.getUserRoleByUserId(userId);
//        // 设置角色id
//        res.setRoles(userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList()));
        Integer userId = res.getId();
        List<SysUserRole> sysUserRoles = roleMapper.getUserRoleByUserId(userId);
        ArrayList<String> roleList = new ArrayList<>();
        for(SysUserRole item : sysUserRoles){
            SysRole sysRole = roleMapper.selectById(item.getRoleId());
            roleList.add(sysRole.getName());
        }
        res.setRoles(roleList);
        for (SysUserRole sysUserRole : sysUserRoles) {
            // 2.根据roleId从role_permission表查询出所有的permissionId
            List<SysRolePermission> sysRolePermissions = permissionMapper.getRolePermissionByRoleId(sysUserRole.getRoleId());
            for (SysRolePermission sysRolePermission : sysRolePermissions) {
                Integer permissionId = sysRolePermission.getPermissionId();
                // 3. 根据permissionId查询permission信息
                SysPermission sysPermission = permissionMapper.selectById(permissionId);
                sysPermissionSet.add(sysPermission);
            }
        }
        // 对资源根据id进行排序
        LinkedHashSet<SysPermission> sortedSet = sysPermissionSet.stream().sorted(Comparator.comparing(SysPermission::getId)).collect(Collectors.toCollection(LinkedHashSet::new));
        //设置当前用户的资源信息
        res.setSysPermissions(sortedSet);
        return Result.success(res);
    }

    @GetMapping("/all")
    public Result<?> findAll() {
        return Result.success(userMapper.selectList(null));
    }

    /**
     * 统计数据
     *
     * @return
     */
//    @GetMapping("/count")
//    public Result<?> count() {
//        User user = getUser(); // 当前登录的用户信息
//        return Result.success(userMapper.countAddress());
//    }


    /**
     * 用户分页列表查询，包含书籍表的一对多查询
     * @param pageNum
     * @param pageSize
     * @param search
     * @return
     */
    @GetMapping
    public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
                              @RequestParam(defaultValue = "10") Integer pageSize,
                              @RequestParam(defaultValue = "") String search) {
//        LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery().orderByAsc(User::getId);
        LambdaQueryWrapper<SysUser> wrapper1 = Wrappers.lambdaQuery();
        if (StrUtil.isNotBlank(search)) {
            wrapper1.like(SysUser::getPeopleName, search);
        }

//        Page<User> userPage = userMapper.findPage(new Page<>(pageNum, pageSize), wrapper1);
        Page<SysUser> userPage = userMapper.selectPage(new Page<>(pageNum, pageSize), wrapper1);

        // 设置用户的角色id列表
        if(userPage.getRecords() != null) {
            for (SysUser record : userPage.getRecords()) {
                List<SysUserRole> roles = roleMapper.getUserRoleByUserId(record.getId());
                List<String> roleNames = new ArrayList<>();
                List<String> roleComments = new ArrayList<>();
                for(SysUserRole item : roles){
                    SysRole sysRole = roleMapper.selectById(item.getRoleId());
                    roleNames.add(sysRole.getName());
                    roleComments.add(sysRole.getComment());
                }
                record.setRoles(roleNames);
                record.setRoleComments(roleComments);

//                List<Integer> roleIds = roles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList());
            }
        }
        return Result.success(userPage);
    }

    /**
     * Excel导出
     *
     * @param response
     * @throws IOException
     */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws IOException {

        List<Map<String, Object>> list = CollUtil.newArrayList();

        List<SysUser> all = userMapper.selectList(null);
        for (SysUser sysUser : all) {
            Map<String, Object> row1 = new LinkedHashMap<>();
            row1.put("用户名", sysUser.getUsername());
            row1.put("昵称", sysUser.getPeopleName());
            list.add(row1);
        }

        // 2. 写excel
        ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.write(list, true);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("用户信息", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(System.out);
    }

    /**
     * Excel导入
     * 导入的模板可以使用 Excel导出的文件
     *
     * @param file Excel
     * @return
     * @throws IOException
     */
    @PostMapping("/import")
    public Result<?> upload(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
        List<SysUser> saveList = new ArrayList<>();
        for (List<Object> row : lists) {
            SysUser sysUser = new SysUser();
            sysUser.setUsername(row.get(0).toString());
            sysUser.setPeopleName(row.get(1).toString());
            saveList.add(sysUser);
        }
        for (SysUser sysUser : saveList) {
            userMapper.insert(sysUser);
        }
        return Result.success();
    }

}
